package dmxGroupControl.solvers;

import dmxGroupControl.Fixture;
import dmxGroupControl.Group;
import dmxGroupControl.PixelFixture;
import org.jdom2.Attribute;
import org.jdom2.Element;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collection;

public abstract class Solver
{
	boolean enabled = true;
	
    public abstract String GetType();
	public abstract void Set(String attributeName, float value);
	public abstract boolean SolvesAttribute(String attribute);
	protected abstract void SolveInternal();
	
	public void Solve()
	{
		if(enabled)
		{
			SolveInternal();
		}
	}
	
	public boolean GetEnabled()
	{
		return enabled;
	}
	
	public void SetEnabled(boolean value)
	{
		this.enabled = value;
	}
	
	protected static boolean GetIsApplicableToFixture(Fixture fixture)
	{
	    return false;
	}
	
	protected static boolean SolvesForChannel(String needle, Collection<String> solvableChannels)
	{
	    for(String channel : solvableChannels)
	    {
	        if(channel.equals(needle))
	        {
	            return true;
	        }
	    }
	    return false;
	}
	
    protected static boolean SolvesAttribute(String needle, Collection<String> solvableAttributes)
    {
        return solvableAttributes
            .stream()
            .anyMatch(attribute -> attribute.equals(needle));
    }
    
	protected static boolean GetIsApplicableToFixture(Fixture fixture, Collection<String> solvableChannels)
	{
	    ArrayList<String> fixtureChannels = new ArrayList<>(fixture.GetChannels().toStrings());
        fixtureChannels.retainAll(solvableChannels);

        return (fixtureChannels.size() > 0);
	}
	
	public abstract float GetAttribute(String name);
	
	public Collection<? extends Attribute> GetAttributes()
	{
	    return new ArrayList<>();
	}

    public static Solver CreateSolver(Element solverElement, Group group)
    {
        String solverType = solverElement.getAttributeValue("type");
        switch (solverType)
        {
            case "simpleChase":
                int maxDistance = Integer.parseInt(solverElement.getAttributeValue("maxDistance"));
                return new SimpleChaseSolver(group, maxDistance);
            case "apeshit":
                int countdownFrames = Integer.parseInt(solverElement.getAttributeValue("countdownFrames"));
                return new ApeShitSolver(group, countdownFrames);
            default:
                return null;
        }
    }

    public static Solver CreateSolver(@NotNull Element solverElement, Fixture fixture)
    {
        String solverType = solverElement.getAttributeValue("type");
        switch (solverType)
        {
            case "lookAt":
                return new LookAtSolver(
                    Float.parseFloat(solverElement.getAttributeValue("x")),
                    Float.parseFloat(solverElement.getAttributeValue("y")),
                    Float.parseFloat(solverElement.getAttributeValue("z")),
                    fixture);
            case "fakeStrobe":
                int interval = Integer.parseInt(solverElement.getAttributeValue("countdownFrames"));
                return new FakeStrobeSolver(fixture, interval);
            case "hsb":
                return new HSBSolver(fixture);
            case "masterAtFull":
                return new MasterAtFullSolver(fixture);
            case "pixel":
                return new PixelSolver((PixelFixture) fixture);
            case "colorwheel":
                return new ColorWheelSolver(fixture);
            default:
                throw new IllegalArgumentException("No such solver as " + solverType);
        }

    }
}
